package com.yingxin.yxerp.module.activiti.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.yingxin.yx.framework.commons.activiti.ApprovalStatus;
import com.yingxin.yx.framework.commons.activiti.def.TaskDef;
import com.yingxin.yx.framework.commons.activiti.dto.AuditDto;
import com.yingxin.yx.framework.commons.activiti.dto.UserCandidateDto;
import com.yingxin.yx.framework.commons.activiti.enums.AuditAction;
import com.yingxin.yx.framework.commons.activiti.enums.FormKey;
import com.yingxin.yx.framework.commons.constant.CommonConst;
import com.yingxin.yx.framework.commons.dto.AttachmentDto;
import com.yingxin.yx.framework.commons.enums.BusinessType;
import com.yingxin.yx.framework.commons.exception.BizException;
import com.yingxin.yx.framework.commons.helper.ListHelper;
import com.yingxin.yx.framework.commons.id.IdHelper;
import com.yingxin.yx.framework.user.core.IUserSupport;
import com.yingxin.yxerp.module.activiti.api.ProcessService;
import com.yingxin.yxerp.module.activiti.entity.*;
import com.yingxin.yxerp.module.activiti.mapper.ActHiTaskInstMapper;
import com.yingxin.yxerp.module.activiti.mapper.ActivitiBizInfoMapper;
import com.yingxin.yxerp.module.activiti.vo.resp.ActivitiFormRespVo;
import com.yingxin.yxerp.module.appversion.entity.AppPush;
import com.yingxin.yxerp.module.appversion.manager.AppPushUtils;
import com.yingxin.yxerp.module.appversion.service.IAppPushService;
import com.yingxin.yxerp.module.attachment.constant.AttachConst;
import com.yingxin.yxerp.module.attachment.service.IAttachmentService;
import com.yingxin.yxerp.module.common.BusinessTypeHelper;
import com.yingxin.yxerp.module.organization.entity.Department;
import com.yingxin.yxerp.module.organization.entity.DepartmentMgr;
import com.yingxin.yxerp.module.organization.entity.User;
import com.yingxin.yxerp.module.organization.service.IDepartmentMgrService;
import com.yingxin.yxerp.module.organization.service.IDepartmentService;
import com.yingxin.yxerp.module.organization.service.IUserService;
import com.yingxin.yxerp.module.print.constant.PrintStatusConst;
import com.yingxin.yxerp.module.print.entity.PrintBusinessStat;
import com.yingxin.yxerp.module.print.service.IPrintBusinessStatService;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActivitiProcessService implements ProcessService {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IActivitiFormService activitiFormService;

    @Autowired
    private IUserSupport userSupport;

    @Autowired
    private IUserService userService;

    @Autowired
    private IDepartmentService departmentService;

    @Autowired
    private IDepartmentMgrService departmentMgrService;

    @Autowired
    private IActivitiBizInfoService activitiBizInfoService;

    @Autowired
    @SuppressWarnings("all")
    private ActivitiBizInfoMapper activitiBizInfoMapper;

    @Autowired
    private IAttachmentService attachmentService;

    @Autowired
    private IPrintBusinessStatService printBusinessStatService;

    @Autowired
    private IActivitiFormBpmnService activitiFormBpmnService;

    @Autowired
    private IActivitiReplaceInfoService activitiReplaceInfoService;

    @Autowired
    private ActHiTaskInstMapper actHiTaskInstMapper;

    @Autowired
    private IAppPushService appPushService;

    /**
     * 查询流程定义
     */
    public ProcessDefinition getProcessDefinitionById(String definitionId) {
        return repositoryService.createProcessDefinitionQuery().processDefinitionId(definitionId).singleResult();
    }

    /**
     * 创建流程实例
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void startProcessInstance(BusinessType businessType, String businessId, String businessNo, Map<String, Object> variables) {
        // 查询流程表单
        ActivitiFormBpmn activitiFormBpmn = activitiFormBpmnService.getById(businessType.getType());
        ActivitiForm activitiForm = activitiFormService.getById(businessType.getType());
        if (activitiFormBpmn == null || activitiFormBpmn.getProcessDefinitionId() == null) {
            throw new BizException(activitiForm.getName() + " 流程定义为空");
        }
        String startUserId = userSupport.getUserId();
        variables = addAssigneeVariables(startUserId, variables);
        try {
            String userId = userSupport.getUserId();
            // 启动者 UserId
            Authentication.setAuthenticatedUserId(userId);
            // ProcessInstance 对应 数据库表为 act_ru_execution
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(activitiFormBpmn.getProcessDefinitionId(),
                    businessId, variables);
            // 更新部门主管
            updateTaskDepartmentMgr(processInstance);
            // 其他信息
            // ActivitiBizInfo
            ActivitiBizInfo bizInfo = new ActivitiBizInfo();
            bizInfo.setBizId(businessId);
            bizInfo.setBizType(businessType.getType());
            bizInfo.setBizNo(businessNo);
            bizInfo.setApplicantId(userId);
            bizInfo.setProcessDefinitionId(activitiFormBpmn.getProcessDefinitionId());
            bizInfo.setProcessInstanceId(processInstance.getProcessInstanceId());
            bizInfo.setBpmnTask(activitiFormBpmn.getBpmnTask());
            bizInfo.setApprovalStatus(ApprovalStatus.PENDING_APPROVAL.getStatus());
            bizInfo.setCreatorId(userId);
            bizInfo.setCreateTime(processInstance.getStartTime());
            List<String> assigneeList = getAssigneeListByProcessInstanceId(processInstance.getProcessInstanceId());
            bizInfo.setCurrentAssigneeInfo(String.join(",", assigneeList));
            activitiBizInfoService.save(bizInfo);
            // 打印
            List<TaskDef> taskDefList = JSON.parseArray(bizInfo.getBpmnTask(), TaskDef.class);
            for (TaskDef taskDef : taskDefList) {
                // app 推送
                List<String> users = taskDef.getCandidateUsers();
                if (users != null) {
                    for (String user : users) {
                        //AppPushUtils.httpPush(user,);
                    }
                }

                if (FormKey.PRINT_LIMIT.getKey().equals(taskDef.getFormKey())
                        || FormKey.DEDUCT.getKey().equals(taskDef.getFormKey())
                        || FormKey.PRINT_INCOME.getKey().equals(taskDef.getFormKey())) {
                    PrintBusinessStat printBusiness = new PrintBusinessStat();
                    printBusiness.setBusinessId(businessId);
                    printBusiness.setBusinessNo(businessNo);
                    printBusiness.setBusinessType(businessType.getType());
                    printBusiness.setPrintStatus(PrintStatusConst.AFTER_APPROVED);
                    printBusinessStatService.saveOrUpdate(printBusiness);
                    break;
                }

            }
            getAuditor(processInstance);
        } catch (ActivitiException e) {
            analyseException(activitiForm, e);
        }
    }

    /**
     * 创建流程实例
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void startProcessInstance(BusinessType businessType, String businessId, String businessNo,
                                     Map<String, Object> variables, String startUserId) {
        // 查询流程表单
        ActivitiFormBpmn activitiFormBpmn = activitiFormBpmnService.getById(businessType.getType());
        ActivitiForm activitiForm = activitiFormService.getById(businessType.getType());
        if (activitiFormBpmn == null || activitiFormBpmn.getProcessDefinitionId() == null) {
            throw new BizException(activitiForm.getName() + " 流程定义为空");
        }
        variables = addAssigneeVariables(startUserId, variables);
        try {
            String userId = startUserId;
            // 启动者 UserId
            Authentication.setAuthenticatedUserId(userId);
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(activitiFormBpmn.getProcessDefinitionId(),
                    businessId, variables);
            // 更新部门主管
            updateTaskDepartmentMgr(processInstance);
            // 其他信息
            // ActivitiBizInfo
            ActivitiBizInfo bizInfo = new ActivitiBizInfo();
            bizInfo.setBizId(businessId);
            bizInfo.setBizType(businessType.getType());
            bizInfo.setBizNo(businessNo);
            bizInfo.setApplicantId(userId);
            bizInfo.setProcessDefinitionId(activitiFormBpmn.getProcessDefinitionId());
            bizInfo.setProcessInstanceId(processInstance.getProcessInstanceId());
            bizInfo.setBpmnTask(activitiFormBpmn.getBpmnTask());
            bizInfo.setApprovalStatus(ApprovalStatus.PENDING_APPROVAL.getStatus());
            bizInfo.setCreatorId(userId);
            bizInfo.setCreateTime(processInstance.getStartTime());
            List<String> assigneeList = getAssigneeListByProcessInstanceId(processInstance.getProcessInstanceId());
            bizInfo.setCurrentAssigneeInfo(String.join(",", assigneeList));
            activitiBizInfoService.save(bizInfo);
            // 打印
            List<TaskDef> taskDefList = JSON.parseArray(bizInfo.getBpmnTask(), TaskDef.class);
            for (TaskDef taskDef : taskDefList) {
                if (FormKey.PRINT_LIMIT.getKey().equals(taskDef.getFormKey())
                        || FormKey.DEDUCT.getKey().equals(taskDef.getFormKey())
                        || FormKey.PRINT_INCOME.getKey().equals(taskDef.getFormKey())) {
                    PrintBusinessStat printBusiness = new PrintBusinessStat();
                    printBusiness.setBusinessId(businessId);
                    printBusiness.setBusinessNo(businessNo);
                    printBusiness.setBusinessType(businessType.getType());
                    printBusiness.setPrintStatus(PrintStatusConst.AFTER_APPROVED);
                    printBusinessStatService.saveOrUpdate(printBusiness);
                    break;
                }
            }
        } catch (ActivitiException e) {
            analyseException(activitiForm, e);
        }
    }


    /**
     * 查询流程实例 by instanceId
     */
    public ProcessInstance getProcessInstanceById(String instanceId) {
        return runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
    }

    /**
     * 查询流程实例 by instanceIds
     */
    public List<ProcessInstance> listProcessInstanceByIds(Set<String> instanceIds) {
        if (CollectionUtil.isEmpty(instanceIds)) {
            return new ArrayList<>();
        }
        return runtimeService.createProcessInstanceQuery().processInstanceIds(instanceIds).list();
    }

    /**
     * 查询历史流程 by instanceId
     */
    public HistoricProcessInstance getHistoricProcessInstanceById(String instanceId) {
        return historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
    }

    /**
     * 查询历史流程 by instanceIds
     */
    public List<HistoricProcessInstance> listHistoricProcessInstanceByIds(Set<String> instanceIds) {
        if (CollectionUtil.isEmpty(instanceIds)) {
            return new ArrayList<>();
        }
        return historyService.createHistoricProcessInstanceQuery().processInstanceIds(instanceIds).list();
    }

    /**
     * 删除流程实例
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteProcessInstanceById(String instanceId, String reason) {
        // ACT_RU_TASK ACT_RU_IDENTITYLINK ACT_RU_EXECUTION
        // ACT_HI_PROCINST ACT_HI_ACTINST ACT_HI_TASKINST
        runtimeService.deleteProcessInstance(instanceId, reason);
    }

    /* ***** 用户任务 ***** */

    public Task getTaskById(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }

    /**
     * ProcessDefinitionKey
     */
    public String getProcessDefinitionKeyByTaskId(String taskId) {
        Task task = getTaskById(taskId);
        ProcessDefinition processDefinition = getProcessDefinitionById(task.getProcessDefinitionId());
        return processDefinition.getKey();
    }


    /**
     * 获取 BusinessKey by taskId
     */
    public String getBusinessKeyByTaskId(String taskId) {
        Task task = getTaskById(taskId);
        return task.getBusinessKey();
    }

    /**
     * 获取 BusinessId by taskId
     */
    public String getBusinessIdByTaskId(String taskId) {
        Task task = getTaskById(taskId);
        return task.getBusinessKey();
    }


    /**
     * 获取 getFormKey by taskId
     */
    public String getFormKeyByTaskId(String taskId) {
        Task task = getTaskById(taskId);
        return task.getFormKey();
    }


    /**
     * 查询当前任务 by processInstanceId
     */
    public List<Task> listTaskByProcessInstanceId(String processInstanceId) {
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();
        if (CollectionUtil.isEmpty(taskList)) {
            return new ArrayList<>();
        } else {
            return taskList;
        }
    }

    /**
     * 查询历史任务 by taskId
     */
    public HistoricTaskInstance getHistoricTaskById(String taskId) {
        return historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
    }

    /**
     * 查询历史任务 by processInstanceId
     */
    public List<HistoricTaskInstance> listHistoricTaskByProcessInstanceId(String processInstanceId) {
        return historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();
    }

    /**
     * 查询历史任务 by processInstanceId
     */
    public List<HistoricTaskInstance> listHistoricTaskByProcessInstanceId2(String processInstanceId) {
        return historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceEndTime().asc().list();
    }

    /**
     * 查询当前的任务
     */
    public Task getTaskByAssigneeAndId(String taskId, String userId) {
        User user = userService.getById(userId);
        // 查询审核人
        Task task = taskService.createTaskQuery().taskId(taskId).taskAssignee(userId).singleResult();
        // 查询候选人
        if (task == null) {
            task = taskService.createTaskQuery().taskId(taskId).taskCandidateUser(userId).singleResult();
        }
        // 查询候选部门
        if (task == null && StringUtils.isNotEmpty(user.getDeptId())) {
            task = taskService.createTaskQuery().taskId(taskId).taskCandidateGroup(user.getDeptId()).singleResult();
        }
        return task;
    }

    /*public Task getTaskByAssigneeAndIdBak(String taskId, String userId) {
        User user = userService.getById(userId);
        // 查询审核人
        UserTaskDto dto = activitiBizInfoMapper.findTaskByAssignee(userId, taskId);
        // 查询候选人
        if (dto == null) {
            dto = activitiBizInfoMapper.findTaskByCandidateUser(userId, taskId);
        }
        // 查询候选部门
        if (dto == null && StringUtils.isNotEmpty(user.getDeptId())) {
            dto = activitiBizInfoMapper.findTaskByCandidateGroup(user.getDeptId(), taskId);
        }
        if (dto == null) {
            throw new BizException("无权操作");
        }
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        return task;
    }*/

    /**
     * 完成任务
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public ApprovalStatus approved(AuditDto auditDto, User user, TaskDef taskDef, ActivitiBizInfo bizInfo) {
        // 判断签名
        AttachmentDto attachment = attachmentService.getByBiz(user.getId(), BusinessType.USER, AttachConst.SIGN);
        if (attachment == null) {
            throw new BizException("请先点击右上角账号设置，打开弹窗保存个人签名");
        }
        // task
        String taskId = auditDto.getTaskId();
        Task task = getTaskByAssigneeAndId(taskId, user.getId());
        if (task == null) {
            throw new BizException("无权操作");
        }
        auditDto.setFormKey(task.getFormKey());

        // 流程实例
        ProcessInstance processInstance = getProcessInstanceById(task.getProcessInstanceId());
        String businessKey = processInstance.getBusinessKey();
        String processInstanceId = processInstance.getId();

        // FINAL_APPROVE 这个判断停工记录例外
        if (AuditAction.FINAL_APPROVE.equals(auditDto.getAction()) && !BusinessType.TGJL.getType().equals(bizInfo.getBizType())) {
            // 判断任务是否可操作
            if (taskDef.getActions() == null || !taskDef.getActions().contains("FA")) {
                throw new BizException("您无法结束流程");
            }
        }

        // 参数
        Map<String, Object> variables = addAssigneeVariables(processInstance.getStartUserId(), auditDto.getVariables());
        taskService.setVariables(taskId, variables);
        ActivitiForm activitiForm = activitiFormService.getById(bizInfo.getBizType());
        try {
            //Attachment att1 = taskService.createAttachment("attachmentType", task.getId(), processInstance.getId(), "attachmentName",
            //        "attachmentDescription", "url");

            // 拾取任务
            if (task.getAssignee() == null) {
                taskService.claim(taskId, user.getId());
            }

            // 任务意见
            if (StringUtils.isNotEmpty(auditDto.getComment())) {
                taskService.addComment(taskId, processInstance.getId(), auditDto.getComment());
            }

            // 判断有无代办人
            if (!CollectionUtil.isEmpty(taskDef.getReplacePersonIdList())) {
                // 判断当前审核人是代办人
                if (taskDef.getReplacePersonIdList().contains(user.getId())) {
                    // 修改历史记录
                    HistoricTaskInstance historicTaskById = getHistoricTaskById(taskId);
                    ActHiTaskInst actHiTaskInst = new ActHiTaskInst();
                    actHiTaskInst.setID_(historicTaskById.getId());
                    actHiTaskInst.setNAME_(historicTaskById.getName() + "(代办)");
                    actHiTaskInstMapper.updateName(actHiTaskInst);
                    // 待确认人
                    List<String> personList = taskDef.getCandidateUsers().stream().filter(element -> !taskDef.getReplacePersonIdList().contains(element))
                            .collect(Collectors.toList());
                    for (String person : personList) {
                        // 代办信息添加
                        ActivitiReplaceInfo activitiReplaceInfo = new ActivitiReplaceInfo();
                        activitiReplaceInfo.setId(IdHelper.snowflakeId());
                        activitiReplaceInfo.setBizId(bizInfo.getBizId());
                        activitiReplaceInfo.setBizNo(bizInfo.getBizNo());
                        activitiReplaceInfo.setBizType(bizInfo.getBizType());
                        activitiReplaceInfo.setConfirmId(person);
                        activitiReplaceInfo.setCreatorId(user.getId());
                        activitiReplaceInfo.setCreateTime(new Date());
                        activitiReplaceInfoService.save(activitiReplaceInfo);
                    }
                }
            }
            // 完成任务
            taskService.complete(taskId);

            // 更新部门主管
            updateTaskDepartmentMgr(processInstance);

            // FINAL_APPROVE
            if (AuditAction.FINAL_APPROVE.equals(auditDto.getAction())) {
                // 流程实例
                processInstance = getProcessInstanceById(task.getProcessInstanceId());
                if (processInstance != null) {
                    List<Task> tasks = listTaskByProcessInstanceId(task.getProcessInstanceId());
                    for (Task t : tasks) {
                        taskService.setAssignee(t.getId(), null);
                    }
                    // 删除实例
                    deleteProcessInstanceById(task.getProcessInstanceId(), null);
                }
            }
        } catch (ActivitiException e) {
            analyseException(activitiForm, e);
        }

        // historic ProcessInstance
        HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(task.getProcessInstanceId());
        Date endTime = historicProcessInstance.getEndTime();

        // FINAL_APPROVE
        if (AuditAction.FINAL_APPROVE.equals(auditDto.getAction()) && endTime == null) {
            throw new BizException("完成异常");
        }

        // 根据endTime判断流程是否结束
        if (endTime != null) {
            activitiBizInfoService.updateApprovalStatus(businessKey, ApprovalStatus.APPROVED, user.getStaffName(), null);
            //申请人
            String applicantId = bizInfo.getApplicantId();
            User pushUser = userService.getById(applicantId);
            Map<String, String> pushInfo = new HashMap<>();
            pushInfo.put("title",activitiForm.getName());
            pushInfo.put("content","您申请的" + activitiForm.getName() + "已通过");
            checkPush(pushUser,pushInfo);
            return ApprovalStatus.APPROVED;
        } else {
            List<String> assigneeList = getAssigneeListByProcessInstanceId(processInstanceId);
            activitiBizInfoService.updateApprovalStatus(businessKey, ApprovalStatus.PENDING_APPROVAL, user.getStaffName(),
                    String.join(",", assigneeList));
            getAuditor(processInstance);
            return ApprovalStatus.PENDING_APPROVAL;
        }
    }

    /**
     * 审核不通过
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public ApprovalStatus unapproved(AuditDto auditDto, User user, TaskDef taskDef) {
        String taskId = auditDto.getTaskId();
        Task task = getTaskByAssigneeAndId(taskId, user.getId());
        if (task == null) {
            throw new BizException("无权操作");
        }
        if (StringUtils.isEmpty(auditDto.getComment())) {
            throw new BizException("不通过原因不能为空");
        }
        auditDto.setFormKey(null);

        // 判断任务是否可操作
        if (taskDef.getActions() == null || !taskDef.getActions().contains("R")) {
            throw new BizException("您无法审核拒绝");
        }

        // 拾取任务
        if (task.getAssignee() == null) {
            taskService.claim(taskId, user.getId());
        }

        // 任务意见
        if (StringUtils.isNotEmpty(auditDto.getComment())) {
            taskService.addComment(taskId, task.getProcessInstanceId(), auditDto.getComment());
        }
        //申请人
        ActivitiBizInfo bizInfo = activitiBizInfoService.getByProcessInstanceId(task.getProcessInstanceId());
        ActivitiForm activitiForm = activitiFormService.getById(bizInfo.getBizType());
        String applicantId = bizInfo.getApplicantId();
        User pushUser = userService.getById(applicantId);
        Map<String, String> pushInfo = new HashMap<>();
        pushInfo.put("title",activitiForm.getName());
        pushInfo.put("content","您申请的" + activitiForm.getName() + "被拒绝");
        checkPush(pushUser,pushInfo);

        // 删除实例
        deleteProcessInstanceById(task.getProcessInstanceId(), auditDto.getComment());
        activitiBizInfoService.updateApprovalStatus(task.getBusinessKey(), ApprovalStatus.UNAPPROVED, user.getStaffName(), null);
        return ApprovalStatus.UNAPPROVED;
    }

    /**
     * 强制拒绝
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public ApprovalStatus forceApproved(AuditDto auditDto, User user, TaskDef taskDef) {
        String taskId = auditDto.getTaskId();
        // Task task = getTaskByAssigneeAndId(taskId, "23");
        Task task = getTaskById(taskId);
        if (StringUtils.isEmpty(auditDto.getComment())) {
            throw new BizException("不通过原因不能为空");
        }
        auditDto.setFormKey(null);

        // 判断任务是否可操作
        // if (taskDef.getActions() == null || !taskDef.getActions().contains("R")) {
        // throw new BizException("您无法审核拒绝");
        // }

        // 拾取任务
        if (task.getAssignee() == null) {
            taskService.claim(taskId, user.getId());
        }

        // 任务意见
        if (StringUtils.isNotEmpty(auditDto.getComment())) {
            taskService.addComment(taskId, auditDto.getProcessInstanceId(), auditDto.getComment());
        }
        //申请人
        ActivitiBizInfo bizInfo = activitiBizInfoService.getByProcessInstanceId(task.getProcessInstanceId());
        ActivitiForm activitiForm = activitiFormService.getById(bizInfo.getBizType());
        String applicantId = bizInfo.getApplicantId();
        User pushUser = userService.getById(applicantId);
        Map<String, String> pushInfo = new HashMap<>();
        pushInfo.put("title",activitiForm.getName());
        pushInfo.put("content","您申请的" + activitiForm.getName() + "被管理员拒绝");
        checkPush(pushUser,pushInfo);
        // 删除实例
        deleteProcessInstanceById(auditDto.getProcessInstanceId(), auditDto.getComment());
        activitiBizInfoService.updateApprovalStatus(auditDto.getBusinessId(), ApprovalStatus.UNAPPROVED, user.getStaffName(), null);
        return ApprovalStatus.UNAPPROVED;
    }

    /**
     * 申请人取消
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public ApprovalStatus auditCancel(AuditDto auditDto) {
        String userId = userSupport.getUserId();
        User user = userService.getById(userId);
        // 流程实例
        ProcessInstance processInstance = getProcessInstanceById(auditDto.getProcessInstanceId());
        if (!processInstance.getStartUserId().equals(userId)) {
            throw new BizException("你不是流程发起人，无法撤销");
        }

        // 流程实例的任务是否已审核
        List<HistoricTaskInstance> taskList = listHistoricTaskByProcessInstanceId(processInstance.getId());
        for (HistoricTaskInstance task : taskList) {
            if (task.getEndTime() != null) {
                throw new BizException("已被审核，无权撤销");
            }
        }

        // 删除实例
        deleteProcessInstanceById(auditDto.getProcessInstanceId(), auditDto.getComment());
        activitiBizInfoService.updateApprovalStatus(processInstance.getBusinessKey(), ApprovalStatus.CANCEL,
                user.getStaffName(), null);
        return ApprovalStatus.CANCEL;
    }

    /**
     * 所有可以审核的人
     */
    private List<String> getAssigneeListByProcessInstanceId(String processInstanceId) {
        List<Task> taskList = listTaskByProcessInstanceId(processInstanceId);
        List<String> assigneeList = new ArrayList<>();
        for (Task t : taskList) {
            if (StringUtils.isBlank(t.getAssignee())) {
                assigneeList.add(getCandidateAssigneeNameByTask(t.getId()));
            } else {
                assigneeList.add(userService.getStaffNameById(t.getAssignee()));
            }
        }
        return assigneeList;
    }

    /**
     * 构建 assignee 参数
     */
    private Map<String, Object> addAssigneeVariables(String startUserId, Map<String, Object> variables) {
        if (variables == null) {
            variables = new HashMap<>();
        }
        // 申请人
        User startUser = userService.getById(startUserId);
        variables.put("applicant", startUser.getId());
        /*
        // 申请人部门主管
        Department applicantDepartment = departmentService.getById(startUser.getDeptId());
        if (applicantDepartment != null && StringUtils.isNotEmpty(applicantDepartment.getManagerId())) {
            variables.put("applicantMgr", applicantDepartment.getManagerId());
        }
        // 所有部门主管
        List<Department> departmentList = departmentService.list();
        for (Department dept : departmentList) {
            if (StringUtils.isNotEmpty(dept.getManagerId())) {
                variables.put("deptMgr_" + dept.getId(), dept.getManagerId());
            }
        }
         */
        return variables;
    }


    @Transactional(rollbackFor = RuntimeException.class)
    public void updateTaskDepartmentMgr(ProcessInstance processInstance) {
        String processInstanceId = processInstance.getId();
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        for (Task task : taskList) {
            String assignee = task.getAssignee();
            if (StringUtils.isNotBlank(assignee)) {
                if (assignee.startsWith("deptMgr_")) {
                    String[] array = assignee.split("deptMgr_");
                    if (array.length != 2) {
                        throw new BizException(String.format("[%s]：deptMgr异常", BusinessTypeHelper.getName(processInstance.getProcessDefinitionKey())));
                    }
                    List<DepartmentMgr> mgrList = departmentMgrService.listByDeptId(array[1]);
                    if (CollectionUtil.isEmpty(mgrList)) {
                        throw new BizException(String.format("[%s]：相关部门主管为空", BusinessTypeHelper.getName(processInstance.getProcessDefinitionKey())));
                    }
                    taskService.setAssignee(task.getId(), null);
                    Set<String> managerIdSet = ListHelper.toSet(DepartmentMgr::getManagerId, mgrList);
                    for (String mgrId : managerIdSet) {
                        taskService.addCandidateUser(task.getId(), mgrId);
                    }
                } else if (assignee.equals("applicantMgr")) {
                    // 申请人主管
                    String startUserId = processInstance.getStartUserId();
                    User startUser = userService.getById(startUserId);
                    if (StringUtils.isBlank(startUser.getDeptId())) {
                        throw new BizException(String.format("[%s]：申请人没有所属部门", BusinessTypeHelper.getName(processInstance.getProcessDefinitionKey())));
                    }
                    List<DepartmentMgr> mgrList = departmentMgrService.recursionFindByDeptId(startUser.getDeptId(), startUserId);
                    if (CollectionUtil.isEmpty(mgrList)) {
                        throw new BizException(String.format("[%s]：申请人部门主管为空", BusinessTypeHelper.getName(processInstance.getProcessDefinitionKey())));
                    }
                    taskService.setAssignee(task.getId(), null);
                    Set<String> managerIdSet = ListHelper.toSet(DepartmentMgr::getManagerId, mgrList);
                    for (String mgrId : managerIdSet) {
                        taskService.addCandidateUser(task.getId(), mgrId);

                    }
                }
                /*
                if (AssigneeType.APPLICANT.getType().equals(assignee)) {
                    // 申请人
                    taskService.setAssignee(task.getId(), startUser.getId());
                } else if (AssigneeType.APPLICANT_MGR.getType().equals(assignee)) {
                    // 申请人主管
                    Department department = departmentService.getById(startUser.getDeptId());
                    if (department == null) {
                        throw new BizException("申请人不属于任何部门");
                    }
                    if (StringUtils.isEmpty(department.getManagerId())) {
                        throw new BizException("申请人的部门主管为空");
                    }
                    taskService.setAssignee(task.getId(), department.getManagerId());
                }
                 */
            }
        }
    }

    /**
     * 获取 Candidate 审核人名称
     */
    public String getCandidateAssigneeNameByTask(String taskId) {
        List<UserCandidateDto> candidateList = activitiBizInfoMapper.findCandidateByTaskId(taskId);
        List<String> userIds = new ArrayList<>();
        List<String> deptIds = new ArrayList<>();
        for (UserCandidateDto dto : candidateList) {
            if (StringUtils.isNotBlank(dto.getUserId())) {
                userIds.add(dto.getUserId());
            } else if (StringUtils.isNotBlank(dto.getGroupId())) {
                deptIds.add(dto.getGroupId());
            }
        }
        String name = "";
        if (CollectionUtil.isNotEmpty(userIds)) {
            List<User> users = userService.listByIds(userIds);
            if (CollectionUtil.isNotEmpty(users)) {
                List<String> names = ListHelper.toList(User::getStaffName, users);
                name = String.join(",", names);
            }
        } else if (CollectionUtil.isNotEmpty(deptIds)) {
            List<Department> departments = departmentService.listByIds(deptIds);
            if (CollectionUtil.isNotEmpty(departments)) {
                List<String> names = ListHelper.toList(Department::getName, departments);
                name = String.join(",", names);

            }
        }
        return name;
    }

    /**
     * 判断异常原因
     */
    private void analyseException(ActivitiForm activitiForm, ActivitiException e) {
        String msg = e.getMessage();
        if (msg.contains("${applicant}")) {
            throw new BizException(activitiForm.getName() + "：申请人异常");
        } else if (msg.contains("${applicantMgr}")) {
            throw new BizException(activitiForm.getName() + "：申请人的部门主管为空");
        } else if (msg.contains("${deptMgr_")) {
            throw new BizException(activitiForm.getName() + "：相关部门主管为空");
        } else if (msg.contains("No outgoing")) {
            throw new BizException(activitiForm.getName() + "：不满足子流程条件，流程无法继续");
        } else {
            throw e;
        }
    }

    /**
     * 推送审核人
     *
     * @param processInstance
     */
    private void getAuditor(ProcessInstance processInstance) {
        // 当前任务实例
        ActivitiFormRespVo vo = activitiFormService.getVo(processInstance.getProcessDefinitionKey());
        Map<String, String> pushInfo = new HashMap<>();
        pushInfo.put("title",vo.getName());
        pushInfo.put("content","您有一条新的审核信息");
        String processInstanceId = processInstance.getId();
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        ActivitiBizInfo bizInfo = activitiBizInfoService.getByProcessInstanceId(processInstanceId);
        List<TaskDef> taskDefList = JSON.parseArray(bizInfo.getBpmnTask(), TaskDef.class);
        Map<String, TaskDef> taskDefMap = ListHelper.toMap(TaskDef::getElementId, taskDefList);
        for (Task task : taskList) {
            TaskDef taskDef = taskDefMap.get(task.getTaskDefinitionKey());
            if (taskDef.getAssigneeType().equals("USER")) {
                // 指定人
                String assignee = taskDef.getAssignee();
                User user = userService.getById(assignee);
                checkPush(user,pushInfo);

            } else if (taskDef.getAssigneeType().equals("APPLICANT")) {
                // 申请人
                String startUserId = processInstance.getStartUserId();
                User user = userService.getById(startUserId);
                checkPush(user,pushInfo);

            } else if (taskDef.getAssigneeType().equals("APPLICANT_MGR")) {
                // 申请人主管
                String startUserId = processInstance.getStartUserId();
                User startUser = userService.getById(startUserId);
                List<DepartmentMgr> mgrList = departmentMgrService.recursionFindByDeptId(startUser.getDeptId(), startUserId);
                Set<String> managerIdSet = ListHelper.toSet(DepartmentMgr::getManagerId, mgrList);
                for (String userId : managerIdSet) {
                    User user = userService.getById(userId);
                    checkPush(user,pushInfo);
                }

            } else if (taskDef.getAssigneeType().equals("CANDIDATE_USERS")) {
                //  指定多个候选人
                List<String> users = taskDef.getCandidateUsers();
                for (String userId : users) {
                    User user = userService.getById(userId);
                    checkPush(user,pushInfo);
                }

            } else if (taskDef.getAssigneeType().equals("GROUPS")) {
                // 指定组
                List<String> groups = taskDef.getGroups();
                for (String dept : groups) {
                    List<User> users = userService.listByDeptIds(dept);
                    for (User user : users) {
                        checkPush(user,pushInfo);
                    }
                }

            } else if (taskDef.getAssigneeType().equals("DEPT_MGR")) {
                // 指定部门主管
                String deptId = taskDef.getDeptId();
                List<DepartmentMgr> departmentMgrs = departmentMgrService.listByDeptId(deptId);
                for (DepartmentMgr departmentMgr : departmentMgrs) {
                    User user = userService.getById(departmentMgr.getManagerId());
                    checkPush(user,pushInfo);
                }
            }
        }

    }

    /**
     * 验证并推送
     * @param user
     * @param map title 标题，content 内容
     */
    private void checkPush(User user,Map<String,String> map){
        if (CommonConst.TRUE.equals(user.getAccountStatus())){
            AppPush push = appPushService.getUserIdVo(user.getId());
            if (!Objects.isNull(push) ){
                if (CommonConst.TRUE.equals(push.getIsPush())){
                    List<String> cid = new ArrayList<>();
                    cid.add(push.getAppId());
                    try {
                        AppPushUtils.httpPush(cid,map);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }

            }
        }

    }

}